/**
 * Created by game on 2016/11/13
 */
(function ($) {
    if (!$ || !$.fn) return;
    if ($.fn.asDatePicker) return;
    
    var DEFAULT_SETTINGS = {};
    var root, table, target, handler, title, timer,
        time = new Date (), today = new Date ();
    
    function build () {
        root = $('<div class="cal-root"/>').on ('mouseover', function () {
            if (timer) {
                clearTimeout (timer);
                timer = null;
            }
        }).on ('mouseout', function () {
            timer = setTimeout (function () {
                root.hide ();
                timer = null;
            }, 500);
        }).appendTo ($(document.body));
        var controlPanel = $('<div class="cal-cp"/>').appendTo (root);
        $('<a class="cal-button cal-close"/>').text (getTitle ('cancel')).on ('click', close).appendTo (controlPanel);
        $('<a class="cal-button cal-clear"/>').text (getTitle ('clear')).on ('click', clear).appendTo (controlPanel);

        var header = $('<div class="cal-header"/>').appendTo (root);
        $('<a class="cal-handler cal-prev-button"/>')
            .attr ('title', getTitle ('year')['prev']).text ('«')
            .on ('click', prevYear)
            .appendTo (header);
        $('<a class="cal-handler cal-prev-button"/>')
            .attr ('title', getTitle ('month')['prev']).text ('‹')
            .on ('click', prevMonth)
            .appendTo (header);
        $('<a class="cal-handler cal-next-button"/>')
            .attr ('title', getTitle ('year')['next']).text ('»')
            .on ('click', nextYear).appendTo (header);
        $('<a class="cal-handler cal-next-button"/>')
            .attr ('title', getTitle ('month')['next']).text ('›')
            .on ('click', nextMonth).appendTo (header);

        title = $('<div class="cal-title"/>').text (titleMonth (time)).appendTo (header);
        
        table = $('<table class="cal-body"/>').appendTo (root);
        var row = $('<tr/>').appendTo (table);
        $('<th class="cal-date-cell cal-week cal-first-row"/>').text (getLabel ('Week')).appendTo (row);
        for (var i = 1; i <= 7; i ++) {
            var cell = $('<th class="cal-date-cell cal-first-row"/>').text (getLabel ('WeekTitles') [i - 1]).appendTo (row);
            if (i == 1 || i == 7) {
                cell.addClass ('cal-weekend');
            }
        }
    }

    function buildBody (month) {
        var t = table [0];
        while (t.rows.length > 1) {
            t.deleteRow (1);
        }
        var date = new Date (time.getFullYear (), time.getMonth (), time.getDate ());
        if (month) {
            date.setMonth (month);
        }
        month = date.getMonth ();
        title.text (titleMonth (time));

        date.setDate (1);
        var week = date.getWeekOfYear (), weeks = date.getWeeksInMonth ();
        date.add (Date.DAY_OF_MONTH, -date.getDay ());
        for (var i = 0; i < weeks; i ++) {
            var row = $('<tr/>').appendTo (table);
            $('<th class="cal-date-cell cal-week"/>').text (week + i).appendTo (row);

            for (var j = 0; j < 7; j ++) {
                var td = $('<td class="cal-date-cell"/>').appendTo (row);
                var cell = $('<a class="cal-date"/>').on ('click', onDateClicked).attr ('title', date.format ()).text (date.getDate ()).appendTo (td);
                if (date.getMonth () != month) {
                    cell.addClass ('cal-ncm');
                } else {
                    if (j == 0 || j == 6) {
                        cell.addClass ('cal-weekend');
                    }
                    if (date.format () == time.format ()) {
                        cell.addClass ('cal-selected');
                    }
                    if (date.format () == today.format ()) {
                        cell.addClass ('cal-today');
                    }
                }

                date.add (Date.DAY_OF_MONTH, 1);
            }
        }
    }

    function getTitle (field) {
        return __CALENDAR_RESOURCE__.Titles [field][__CALENDAR_RESOURCE__.locale] ||
               __CALENDAR_RESOURCE__.Titles [field]['DEFAULT'];
    }

    function getLabel (field) {
        return __CALENDAR_RESOURCE__ [field][__CALENDAR_RESOURCE__.locale] ||
               __CALENDAR_RESOURCE__ ['DEFAULT'];
    }

    function titleMonth (date) {
        return __CALENDAR_RESOURCE__.getMonthTitle [__CALENDAR_RESOURCE__.locale] (date);
    }

    function onDateClicked () {
        var date = $(this).attr ('title'), settings;
        if (handler) {
            handler.text (date);

            settings = handler.data ('settings');
            target   = handler.data ('target');
            if (target.is ('input')) {
                target.val (date);
            } else {
                target.text (date);
            }
            if (settings && ('onselect' in settings)) {
                settings['onselect'] (target, Date.parse (date));
            }
        }

        close ();
    }
    
    function clickHandler () {
        var self = $(this), parent = self.parent (), offset = parent.offset (), value, height,
            pt, pb, bt, bb;
        target = self.data ('target');
        handler = self;
        if (target.is ('input')) {
            value = target.val ();
        } else {
            value = self.text ();
        }
        if (value) {
            time = Date.parseDate (value);
        }
        height = parent.height ();

        pt = parseInt (parent.css ('padding-top'), 10);
        pb = parseInt (parent.css ('padding-bottom'), 10);
        bt = parseInt (parent.css ('border-top-width'), 10);
        bb = parseInt (parent.css ('border-bottom-width'), 10);
        if (pt) height += pt;
        if (pb) height += pb;
        if (bt) height += bt;
        if (bb) height += bb;
        buildBody ();
        root.css ({
            left:offset.left, top: offset.top + height
        }).show ();
    }

    function close () {
        root.hide ();
        if (handler) {
            var settings = handler.data ('settings'), onclose = settings ['onclose'];
            if (onclose && typeof onclose === 'function') {
                onclose ();
            }
        }
    }

    function clear () {

    }
    
    function prevYear () {
        time.add (Date.YEAR, -1);
        buildBody ();
    }
    
    function nextYear () {
        time.add (Date.YEAR, 1);
        buildBody ();
    }
    
    function prevMonth () {
        time.add (Date.MONTH, -1);
        buildBody ();
    }
    function nextMonth () {
        time.add (Date.MONTH, 1);
        buildBody ();
    }

    function onValueChanged () {
        var holder = $(this).data ('holder');
        if (holder) {
            holder.text (this.value);
        }
    }
    
    $.fn.asDatePicker = function (options) {
        options = $.extend ({}, DEFAULT_SETTINGS, options || {});
        return $(this).each (function () {
            var self = $(this), p = self.parent (),
                holder = $('<div class="cal-bar"/>').appendTo (p),
                h = p.height ();
            holder.data ({'settings': options, target: self}).css ({
                height:h, 'line-height':h + 'px'
            }).on ('click', clickHandler);
            if (self.val ()) {
                holder.text (self.val ());
            }
            holder.on ('mouseover', function () {
                if (timer) {
                    clearTimeout (timer);
                    timer = null;
                }
            }).on ('mouseout', function () {
                timer = setTimeout (function () {
                    root.hide ();
                    timer = null;
                }, 500);
            });
            self.data ('holder', holder).hide ();
            if (self.is ('input')) {
                self.unbind ('change', onValueChanged)
                    .on ('change', onValueChanged).on ('propertychange', function () {
                    console.log (this.value);
                });
            }
        });
    };
    
    $(build);
}) (jQuery);